#ifndef RAFT_ROLE
#define RAFT_ROLE

#include "ffz/bit-ops.h"
#include "ffz/raft/raft-log.h"
#define ROLE_FOLLOWER 1
#define ROLE_CANDIDATE 2
#define ROLE_LEADER 3


/**
 * raft-table.c raftNodeTableInit() 
 * will call this method
 * */
void initRoleVariables();

//ROLE_FOLLOWER APIs
/** Follower decide to become Candidate
 * 
 * the follower will send broadcast to other nodes to tell them 
 * it will decide to become the candidate 
 *  
 * this operation is always compound with the resetClockCount(1)
 * */
void TIMER_BecomeCandiate();
/**
 * 1` this will check condition should a node vote for a candidate?
 * 2` if this RPC's term is bigger than currentTerm, the role will back to FOLLOWER
*/
uint8_t RPC_ValidateChecking(uint16_t term, uint16_t candidateId, uint16_t lastLogIndex, uint16_t lastLogTerm);
/**
 * vote for a candidate(not itself)
 * @param term the candidate's now term
 * @param candidateId the ID of the candidate which this node would like to vote.
 * */
void RPC_VoteFor(uint16_t term, uint16_t candidateId);

//ROLE_CANDIDATE APIs
/**
 * periodic send CANDIDATE request
*/
void TIMER_PeriodicCandidateRequest();
/**
 * Candidate has got a vote from other node
 * @return 0 == role not match ; 1 == successfully get a vote
 * */
uint8_t RPC_GetVote();
/**
 * become the leader
 * */
void ROLE_ToLeader();

//ROLE CANDIDATE & FOLLOWER APIs
/**
 * @param term the heart beat's term
 * @param leaderId the packet's leader's ID
 * @param prevIndex the leader's to our special prevIndex
 * @param prevTerm the leader's to our special prevTerm
 * @param commitIndex the leader's sending commitIndex to us
 * @param hasEntry a flag to show if there is the entry exist
 * @param entry a raft-log object
 * @return result should the mote clear the candidateTimer
 * */
uint8_t receiveHeartBeats(uint16_t term, uint16_t leaderId, uint16_t prevIndex, uint16_t prevTerm, uint16_t commitIndex, uint8_t hasEntry, RaftLog *entry);

//ROLE_LEADER APIs
void TIMER_LeaderBeats();
/**
 * receive the Heartbeats response
 * */
void receiveHeartBeatsResp(uint16_t term, uint8_t success, uint16_t matchIndex, uint16_t senderId);
/**
 * add a new log (must be role-leader)
 * */
void OPERATION_AddLog();


//ROLE LEADER & CANDIDATE APIs
void ROLE_ToFollower(uint16_t term);
/**
 * display node's log information
 * */
void OPERATION_ShowLogs();

//getter and setter
uint16_t getCurrentTerm();
uint16_t getVotedFor();
void setCurrentTerm(uint16_t val);
void setVotedFor(uint16_t val);
#endif